/**
 * 广寒宫
 * 网址:www.guanghangong.xyz
 */
package org.moon.framework.autoconfigure.springmvc.accesslog;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

/**
 * POST requestBody获取值
 * @author moon
 */
public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper{
	//私有化一个byte数据，用于存放我们读取出来的数据
    private final byte[] body;

    //修改构造函数，调用私有化的getBodyByte()方法读取我们的json数据，当然是以byte数据的方式
    public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) {
        super(request);
        body = this.getBodyByte(request);
    }
    
    @Override  
    public BufferedReader getReader() throws IOException {  
        return new BufferedReader(new InputStreamReader(getInputStream()));  
    } 

    /**
     * @desc: 重写getInputStream()将获取的数据重新写入以保证Controller可以正常运行
     */
    @Override
    // 重写getInputStream()方法，主要逻辑就是将在构造方法中读取的byte数组，重新写入，并生成一个新的ServletInputStream()流，以此方式让我们的Controller可以顺利获取到数据
    public ServletInputStream getInputStream() throws IOException {
        final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body);
        return new ServletInputStream() {
            @Override
            public boolean isFinished() {
                return false;
            }
            @Override
            public boolean isReady() {
                return false;
            }
            @Override
            public void setReadListener(ReadListener readListener) {
            }
            @Override
            public int read() throws IOException {
                return byteArrayInputStream.read();
            }
        };
    }

    /**
     * @desc: 获取request对象传入的json数据并返回byte数组用于后面重新写入流
     */
    private byte[] getBodyByte(ServletRequest request){
        StringBuffer stringBuffer = new StringBuffer();
        InputStream inputStream = null;
        BufferedReader bufferedReader = null;
        try{
            inputStream = request.getInputStream();
            bufferedReader = new BufferedReader(new InputStreamReader(inputStream,Charset.forName("UTF-8")));
            String line = null;
            while ((line = bufferedReader.readLine()) != null) {
                stringBuffer.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != inputStream) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(null != bufferedReader){
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return stringBuffer.toString().getBytes(Charset.forName("UTF-8"));
    }
}
